package com.managedBean.merchant;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

import org.apache.commons.lang3.SerializationUtils;
import org.primefaces.component.separator.Separator;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultMenuModel;
import org.primefaces.model.menu.DefaultSeparator;
import org.primefaces.model.menu.DefaultSubMenu;
import org.primefaces.model.menu.MenuItem;
import org.primefaces.model.menu.MenuModel;
import org.primefaces.model.menu.Submenu;

import com.controller.merchant.OrganizeMenuController;
import com.dto.merchant.Level1DTO;
import com.dto.merchant.Level2DTO;
import com.dto.merchant.Level3DTO;

@ManagedBean(name = "organizeMenuManagedBean")
@ViewScoped
public class OrganizeMenuManagedBean implements Serializable {
	private static final long serialVersionUID = 5161851901300444096L;
	private MenuModel model;
	protected static UIViewRoot uiViewRoot = new UIViewRoot();
	@ManagedProperty(value = "#{organizeMenuController}")
	private OrganizeMenuController organizeMenuController;
	private List<Level1DTO> l1List;
	private Level1DTO selectedLevel1DTO;
	private Level2DTO selectedLevel2DTO;
	private Level3DTO selectedLevel3DTO;
	private String level1Name;
	private boolean displayl1AddFlag;
	private boolean displayl1EditFlag;
	private MenuModel previewModel;
	private boolean previewMenuFlag;
	private String level2Name;
	private boolean displayl2AddFlag;
	private boolean displayl2EditFlag;
	private String level3Name;
	private boolean displayl3AddFlag;
	private boolean displayl3EditFlag;

	public OrganizeMenuManagedBean() {
		selectedLevel1DTO = new Level1DTO();
		selectedLevel2DTO = new Level2DTO();
		selectedLevel3DTO = new Level3DTO();
	}
	// submenu <column> <submenu><menu Item></menu Item> </submenu> --- </column>  <column> </column>  /submenu
	@PostConstruct
	public void init() {
		try {
			model = new DefaultMenuModel();
			l1List = new ArrayList<Level1DTO>();

			l1List = organizeMenuController.findAll();

//			Submenu root = new Submenu();
//			root.setLabel("All Products");
			for (Level1DTO var : l1List) {
				DefaultSubMenu submenu = new DefaultSubMenu(var.getL1Name());
//				submenu.setLabel(var.getL1Name());
					
				for (Level2DTO l2dto : var.getLevel2Tables()) {
					submenu.addElement(
							addMenuItem(l2dto.getL2Name(), "l2="+l2dto.getL2Id(), "l2MenuItem"));
					submenu.addElement(new DefaultSeparator());
					for (Level3DTO l3dto : l2dto.getLevel3Tables()) {
						submenu.addElement(
								addMenuItem(l3dto.getL3Name(), "l3="+l3dto.getL3Id(),
										"l3MenuItem"));
						submenu.addElement(new DefaultSeparator());
					}
				}
//    			root.getChildren().add(submenu);
//				column.getChildren().add(submenuColumn);
//				submenu.getChildren().add(column);
				model.addElement(submenu);
			}
//			model.addSubmenu(root);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/*
	 * Root -All products Level 1 add all Categories Level 2 add as menu Item to
	 * Level 1 with different style class like bold and color Level 3 add as
	 * menu item to Level 1 with default color and indented
	 */

	public MenuModel getModel() {
		return model;
	}

	public void addMessage(String summary) {
		FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
				summary, null);
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	private MenuItem addMenuItem(String itemValue, String url, String styleClass) {
		DefaultMenuItem item = new DefaultMenuItem();
		item.setValue(itemValue);
		item.setUrl("../ui/catalog.jsf?" + url);
		item.setId("item" + uiViewRoot.createUniqueId());
		item.setAjax(true);
		item.setStyleClass(styleClass);
//		item.setTransient(true);
		// item.setActionExpression(JsfUtils.createActionExpression("#{menuBean.navigation}",
		// String.class));
		// item.addActionListener(this);
		return item;
	}

	public void l1Listener(SelectEvent event) {
		FacesMessage msg = new FacesMessage("L1 Selected",
				((Level1DTO) event.getObject()).getL1Name());
		FacesContext.getCurrentInstance().addMessage(null, msg);
		selectedLevel2DTO = null;
	}

	public void l2Listener(SelectEvent event) {
		FacesMessage msg = new FacesMessage("L2 Selected",
				((Level2DTO) event.getObject()).getL2Name());
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}

	public void l1add() {
		displayl1AddFlag = true;
	}

	public void l1AddEditSave() {
		previewMenuFlag = true;
		previewModel = new DefaultMenuModel();
		List<Level1DTO> dummyList = new ArrayList<Level1DTO>();
		for (Level1DTO level1dto : l1List) {
			dummyList.add(SerializationUtils.clone(level1dto));
		}
		if (displayl1AddFlag) {
			Level1DTO level1dto = new Level1DTO();
			level1dto.setL1Name(getLevel1Name());
			dummyList.add(level1dto);
		} else if (displayl1EditFlag) {
			for (Level1DTO level1dto : dummyList) {
				if (level1dto.getL1Id()
						.equals(getSelectedLevel1DTO().getL1Id())) {
					level1dto.setL1Name(getLevel1Name());
					break;
				}
			}
		}
		DefaultSubMenu root = new DefaultSubMenu();
		root.setLabel("All Products");
		for (Level1DTO var : dummyList) {
			DefaultSubMenu submenu = new DefaultSubMenu();
			submenu.setLabel(var.getL1Name());
			for (Level2DTO l2dto : var.getLevel2Tables()) {
				submenu.addElement(
						addMenuItem(l2dto.getL2Name(), "#", "l2MenuItem"));
				submenu.addElement(new DefaultSeparator());
				for (Level3DTO l3dto : l2dto.getLevel3Tables()) {
					submenu.addElement(
							addMenuItem(l3dto.getL3Name(), "#", "l3MenuItem"));
					submenu.addElement(new DefaultSeparator());
				}
			}
			root.addElement(submenu);
		}
		previewModel.addElement(root);
	}

	public void l1AddEditCancel()  {
		displayl1AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl1EditFlag = false;
		init();
	}

	public void l1AddPublish()  {
		Level1DTO level1dto = new Level1DTO();
		if (displayl1AddFlag) {
			level1dto.setL1Name(getLevel1Name());
			organizeMenuController.createL1Item(level1dto);
		} else if (displayl1EditFlag) {
			level1dto.setL1Id(getSelectedLevel1DTO().getL1Id());
			level1dto.setL1Name(getLevel1Name());
			organizeMenuController.updateL1Item(level1dto);
		}
		FacesMessage msg = new FacesMessage("L1 Published", level1Name);
		FacesContext.getCurrentInstance().addMessage(null, msg);
		init();
		setLevel1Name(null);
		displayl1AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl1EditFlag = false;
	}

	public void l1AddPublishCancel() {
		previewMenuFlag = false;
		previewModel = null;
	}

	public void l1Edit() {
		displayl1EditFlag = true;
		setLevel1Name(getSelectedLevel1DTO().getL1Name());
	}

	public void l2add() {
		displayl2AddFlag = true;
	}

	public void l2Edit() {
		displayl2EditFlag = true;
		setLevel2Name(getSelectedLevel2DTO().getL2Name());
	}

	public void l2AddEditSave() {
		previewMenuFlag = true;
		previewModel = new DefaultMenuModel();
		List<Level1DTO> dummyList = new ArrayList<Level1DTO>();
		for (Level1DTO level1dto : l1List) {
			dummyList.add(SerializationUtils.clone(level1dto));
		}
		if (displayl2AddFlag) {
			Level2DTO level2dto = new Level2DTO();
			level2dto.setL2Name(getLevel2Name());
			Level1DTO level1dto = new Level1DTO();
			level1dto.setL1Id(getSelectedLevel1DTO().getL1Id());
			level2dto.setLevel1dto(level1dto);
			for (Level1DTO l1dto : dummyList) {
				if (l1dto.getL1Id().equals(getSelectedLevel1DTO().getL1Id())) {
					l1dto.getLevel2Tables().add(level2dto);
				}
			}
		} else if (displayl2EditFlag) {
			for (Level1DTO level1dto : dummyList) {
				if (level1dto.getL1Id()
						.equals(getSelectedLevel1DTO().getL1Id())) {
					for (Level2DTO level2dto : level1dto.getLevel2Tables()) {
						if (level2dto.getL2Id().equals(
								getSelectedLevel2DTO().getL2Id())) {
							level2dto.setL2Name(getLevel2Name());
							break;
						}
					}
				}
			}
		}
		DefaultSubMenu root = new DefaultSubMenu();
		root.setLabel("All Products");
		for (Level1DTO var : dummyList) {
			DefaultSubMenu submenu = new DefaultSubMenu();
			submenu.setLabel(var.getL1Name());
			for (Level2DTO l2dto : var.getLevel2Tables()) {
				submenu.addElement(
						addMenuItem(l2dto.getL2Name(), "#", "l2MenuItem"));
				submenu.addElement(new DefaultSeparator());
				for (Level3DTO l3dto : l2dto.getLevel3Tables()) {
					submenu.addElement(
							addMenuItem(l3dto.getL3Name(), "#", "l3MenuItem"));
					submenu.addElement(new DefaultSeparator());
				}
			}
			root.addElement(submenu);
		}
		previewModel.addElement(root);
	}

	public void l2AddEditCancel()  {
		displayl2AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl2EditFlag = false;
		init();
	}

	public void l2AddPublish()  {
		Level2DTO level2dto = new Level2DTO();
		level2dto.setLevel1dto(getSelectedLevel1DTO());
		if (displayl2AddFlag) {
			level2dto.setL2Name(getLevel2Name());
			organizeMenuController.createL2Item(level2dto);
		} else if (displayl2EditFlag) {
			level2dto.setL2Id(getSelectedLevel2DTO().getL2Id());
			level2dto.setL2Name(getLevel2Name());
			organizeMenuController.updateL2Item(level2dto);
		}
		FacesMessage msg = new FacesMessage("L2 Published", level2Name);
		FacesContext.getCurrentInstance().addMessage(null, msg);
		init();
		setLevel1Name(null);
		setLevel2Name(null);
		displayl2AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl2EditFlag = false;
		setSelectedLevel1DTO(null);
		setSelectedLevel2DTO(null);
	}

	public void l2AddPublishCancel() {
		previewMenuFlag = false;
		previewModel = null;
	}

	public void l3add() {
		displayl3AddFlag = true;
	}

	public void l3Edit() {
		displayl3EditFlag = true;
		setLevel3Name(getSelectedLevel3DTO().getL3Name());
	}

	public void l3AddEditSave() {
		previewMenuFlag = true;
		previewModel = new DefaultMenuModel();
		List<Level1DTO> dummyList = new ArrayList<Level1DTO>();
		for (Level1DTO level1dto : l1List) {
			dummyList.add(SerializationUtils.clone(level1dto));
		}
		if (displayl3AddFlag) {
			Level3DTO level3dto = new Level3DTO();
			level3dto.setL3Name(getLevel3Name());
			Level2DTO level2dto = new Level2DTO();
			level2dto.setL2Id(getSelectedLevel2DTO().getL2Id());
			level3dto.setLevel2dto(level2dto);
			for (Level1DTO l1dto : dummyList) {
				if (l1dto.getL1Id().equals(getSelectedLevel1DTO().getL1Id())) {
					for(Level2DTO l2dto:l1dto.getLevel2Tables()){
						if(l2dto.getL2Id().equals(getSelectedLevel2DTO().getL2Id())){
							l2dto.getLevel3Tables().add(level3dto);
							break;
						}
					}
				}
			}
		} else if (displayl3EditFlag) {
			for (Level1DTO level1dto : dummyList) {
				if (level1dto.getL1Id()
						.equals(getSelectedLevel1DTO().getL1Id())) {
					for (Level2DTO level2dto : level1dto.getLevel2Tables()) {
						if (level2dto.getL2Id().equals(
								getSelectedLevel2DTO().getL2Id())) {
							for(Level3DTO level3dto:level2dto.getLevel3Tables()){
								if(level3dto.getL3Id().equals(getSelectedLevel3DTO().getL3Id())){
									level3dto.setL3Name(getLevel3Name());
									break;
								}
							}
							
							
						}
					}
				}
			}
		}
		DefaultSubMenu root = new DefaultSubMenu();
		root.setLabel("All Products");
		for (Level1DTO var : dummyList) {
			DefaultSubMenu submenu = new DefaultSubMenu();
			submenu.setLabel(var.getL1Name());
			for (Level2DTO l2dto : var.getLevel2Tables()) {
				submenu.addElement(
						addMenuItem(l2dto.getL2Name(), "#", "l2MenuItem"));
				submenu.addElement(new DefaultSeparator());
				for (Level3DTO l3dto : l2dto.getLevel3Tables()) {
					submenu.addElement(
							addMenuItem(l3dto.getL3Name(), "#", "l3MenuItem"));
					submenu.addElement(new DefaultSeparator());
				}
			}
			root.addElement(submenu);
		}
		previewModel.addElement(root);
	}

	public void l3AddEditCancel() {
		displayl3AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl3EditFlag = false;
		init();
	}

	public void l3AddPublish()  {
		Level3DTO level3dto = new Level3DTO();
		level3dto.setLevel2dto(getSelectedLevel2DTO());
		if (displayl3AddFlag) {
			level3dto.setL3Name(getLevel3Name());
			organizeMenuController.createL3Item(level3dto);
		} else if (displayl3EditFlag) {
			level3dto.setL3Id(getSelectedLevel3DTO().getL3Id());
			level3dto.setL3Name(getLevel3Name());
			organizeMenuController.updateL3Item(level3dto);
		}
		FacesMessage msg = new FacesMessage("L3 Published", level3Name);
		FacesContext.getCurrentInstance().addMessage(null, msg);
		init();
//		setLevel1Name(null);
//		setLevel2Name(null);
		setLevel3Name(null);
		
		displayl3AddFlag = false;
		previewMenuFlag = false;
		previewModel = null;
		displayl3EditFlag = false;
//		setSelectedLevel1DTO(null);
//		setSelectedLevel2DTO(null);
		setSelectedLevel3DTO(null);
	}

	public void l3AddPublishCancel() {
		previewMenuFlag = false;
		previewModel = null;
	}

	/**
	 * @return the organizeMenuController
	 */
	public OrganizeMenuController getOrganizeMenuController() {
		return organizeMenuController;
	}

	/**
	 * @param organizeMenuController
	 *            the organizeMenuController to set
	 */
	public void setOrganizeMenuController(
			OrganizeMenuController organizeMenuController) {
		this.organizeMenuController = organizeMenuController;
	}

	/**
	 * @param model
	 *            the model to set
	 */
	public void setModel(MenuModel model) {
		this.model = model;
	}

	/**
	 * @return the l1List
	 */
	public List<Level1DTO> getL1List() {
		return l1List;
	}

	/**
	 * @param l1List
	 *            the l1List to set
	 */
	public void setL1List(List<Level1DTO> l1List) {
		this.l1List = l1List;
	}

	/**
	 * @return the selectedLevel1DTO
	 */
	public Level1DTO getSelectedLevel1DTO() {
		return selectedLevel1DTO;
	}

	/**
	 * @param selectedLevel1DTO
	 *            the selectedLevel1DTO to set
	 */
	public void setSelectedLevel1DTO(Level1DTO selectedLevel1DTO) {
		this.selectedLevel1DTO = selectedLevel1DTO;
	}

	/**
	 * @return the selectedLevel2DTO
	 */
	public Level2DTO getSelectedLevel2DTO() {
		return selectedLevel2DTO;
	}

	/**
	 * @param selectedLevel2DTO
	 *            the selectedLevel2DTO to set
	 */
	public void setSelectedLevel2DTO(Level2DTO selectedLevel2DTO) {
		this.selectedLevel2DTO = selectedLevel2DTO;
	}

	/**
	 * @return the selectedLevel3DTO
	 */
	public Level3DTO getSelectedLevel3DTO() {
		return selectedLevel3DTO;
	}

	/**
	 * @param selectedLevel3DTO
	 *            the selectedLevel3DTO to set
	 */
	public void setSelectedLevel3DTO(Level3DTO selectedLevel3DTO) {
		this.selectedLevel3DTO = selectedLevel3DTO;
	}

	/**
	 * @return the level1Name
	 */
	public String getLevel1Name() {
		return level1Name;
	}

	/**
	 * @param level1Name
	 *            the level1Name to set
	 */
	public void setLevel1Name(String level1Name) {
		this.level1Name = level1Name;
	}

	/**
	 * @return the displayl1AddFlag
	 */
	public boolean isDisplayl1AddFlag() {
		return displayl1AddFlag;
	}

	/**
	 * @param displayl1AddFlag
	 *            the displayl1AddFlag to set
	 */
	public void setDisplayl1AddFlag(boolean displayl1AddFlag) {
		this.displayl1AddFlag = displayl1AddFlag;
	}

	/**
	 * @return the previewModel
	 */
	public MenuModel getPreviewModel() {
		return previewModel;
	}

	/**
	 * @param previewModel
	 *            the previewModel to set
	 */
	public void setPreviewModel(MenuModel previewModel) {
		this.previewModel = previewModel;
	}

	/**
	 * @return the previewMenuFlag
	 */
	public boolean isPreviewMenuFlag() {
		return previewMenuFlag;
	}

	/**
	 * @param previewMenuFlag
	 *            the previewMenuFlag to set
	 */
	public void setPreviewMenuFlag(boolean previewMenuFlag) {
		this.previewMenuFlag = previewMenuFlag;
	}

	/**
	 * @return the displayl1EditFlag
	 */
	public boolean isDisplayl1EditFlag() {
		return displayl1EditFlag;
	}

	/**
	 * @param displayl1EditFlag
	 *            the displayl1EditFlag to set
	 */
	public void setDisplayl1EditFlag(boolean displayl1EditFlag) {
		this.displayl1EditFlag = displayl1EditFlag;
	}

	/**
	 * @return the displayl2AddFlag
	 */
	public boolean isDisplayl2AddFlag() {
		return displayl2AddFlag;
	}

	/**
	 * @param displayl2AddFlag
	 *            the displayl2AddFlag to set
	 */
	public void setDisplayl2AddFlag(boolean displayl2AddFlag) {
		this.displayl2AddFlag = displayl2AddFlag;
	}

	/**
	 * @return the displayl2EditFlag
	 */
	public boolean isDisplayl2EditFlag() {
		return displayl2EditFlag;
	}

	/**
	 * @param displayl2EditFlag
	 *            the displayl2EditFlag to set
	 */
	public void setDisplayl2EditFlag(boolean displayl2EditFlag) {
		this.displayl2EditFlag = displayl2EditFlag;
	}

	/**
	 * @return the level2Name
	 */
	public String getLevel2Name() {
		return level2Name;
	}

	/**
	 * @param level2Name
	 *            the level2Name to set
	 */
	public void setLevel2Name(String level2Name) {
		this.level2Name = level2Name;
	}

	/**
	 * @return the level3Name
	 */
	public String getLevel3Name() {
		return level3Name;
	}

	/**
	 * @param level3Name the level3Name to set
	 */
	public void setLevel3Name(String level3Name) {
		this.level3Name = level3Name;
	}

	/**
	 * @return the displayl3AddFlag
	 */
	public boolean isDisplayl3AddFlag() {
		return displayl3AddFlag;
	}

	/**
	 * @param displayl3AddFlag the displayl3AddFlag to set
	 */
	public void setDisplayl3AddFlag(boolean displayl3AddFlag) {
		this.displayl3AddFlag = displayl3AddFlag;
	}

	/**
	 * @return the displayl3EditFlag
	 */
	public boolean isDisplayl3EditFlag() {
		return displayl3EditFlag;
	}

	/**
	 * @param displayl3EditFlag the displayl3EditFlag to set
	 */
	public void setDisplayl3EditFlag(boolean displayl3EditFlag) {
		this.displayl3EditFlag = displayl3EditFlag;
	}

}